package com.weimob.mcloud.wechatwork.customer.mq.handler.externaluser;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.weimob.mcloud.mcloudratelimitercore.common.RatelimiterInfo;
import com.weimob.mcloud.mcloudratelimitercore.common.enums.BizLimitKeyEnum;
import com.weimob.mcloud.mcloudratelimitercore.common.enums.LimitKeyEnum;
import com.weimob.mcloud.mcloudratelimitercore.common.utils.LimitKeyUtils;
import com.weimob.mcloud.wechatwork.common.enums.CommonBizErrorEnum;
import com.weimob.mcloud.wechatwork.common.enums.MainBizDomainEnum;
import com.weimob.mcloud.wechatwork.common.enums.SubBizDomainEnum;
import com.weimob.mcloud.wechatwork.common.utils.BizErrorCodeGenerator;
import com.weimob.mcloud.wechatwork.core.adapter.enums.cdp.CDPMarkTypeEnum;
import com.weimob.mcloud.wechatwork.core.adapter.enums.cdp.CdpMarkMessageEventEnum;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.cdp.request.customer.CDPUserMarkDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.base.RateLimit4CustomerDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.ExternalContactBO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.FollowUserBO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.SelfExternalContactGetBO;
import com.weimob.mcloud.wechatwork.core.adapter.service.cdp.CdpUserAdapterService;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.core.entity.relation.CustomerEmployeeRelation;
import com.weimob.mcloud.wechatwork.core.entity.relation.customer.Customer;
import com.weimob.mcloud.wechatwork.core.entity.relation.employee.Employee;
import com.weimob.mcloud.wechatwork.core.enums.customer.ExternalUserAddWayEnum;
import com.weimob.mcloud.wechatwork.core.enums.employee.EmployeeActiveStatusEnum;
import com.weimob.mcloud.wechatwork.core.service.customer.CustomerService;
import com.weimob.mcloud.wechatwork.core.service.privatesphere.PrivateSphereService;
import com.weimob.mcloud.wechatwork.customer.convertor.customer.CustomerConvert;
import com.weimob.mcloud.wechatwork.customer.domain.CdpDataJsonInfo;
import com.weimob.mcloud.wechatwork.customer.domain.ExternalUserChangeInfo;
import com.weimob.mcloud.wechatwork.customer.externalDependencyProxy.usermanagement.EmployeeProxy;
import com.weimob.mcloud.wechatwork.customer.service.CustomerTagSyncService;
import com.weimob.mcloud.wechatwork.customer.service.common.CustomerCommonService;
import com.weimob.mcloud.wechatwork.customer.third.ChannelAdapterServiceProxy;
import com.weimob.mcloud.wechatwork.customer.third.core.CustomerServiceProxy;
import com.weimob.mcloud.wechatwork.customer.third.customer.CustomerThird;
import com.weimob.soa.common.response.SoaResponse;
import com.weimob.soa.common.utils.SoaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Create Time: 2021年01月18日 16:11
 *
 * @author maosheng.li
 **/
@Service
@Slf4j
public class EditCorpExternaluserHandler implements CorpExternalUserHandler {

    @Autowired
    private CustomerServiceProxy customerServiceProxy;


    @Reference
    private CdpUserAdapterService cdpUserAdapterService;

    @Reference
    private PrivateSphereService privateSphereService;

    @Autowired
    private AddCorpExternaluserHandler addCorpExternaluserHandler;

    @Autowired
    private CustomerCommonService customerCommonService;


    @Autowired
    private CustomerThird customerThird;

    @Autowired
    private CustomerTagSyncService customerTagSyncService;


    @Autowired
    ChannelAdapterServiceProxy channelAdapterServiceProxy;

    @Autowired
    private EmployeeProxy employeeProxy;

    @Reference
    CustomerService customerService;

    @Resource
    RedisTemplate<String, RatelimiterInfo> redisTemplate;

    /**
     * 企微助手产品id
     */
    @Value("${aewc.productId:203}")
    private Long aewcProductId;

    @Override
    public SoaResponse<?, ?> handleCorpExternalUser(ExternalUserChangeInfo externalUserChageInfo) {

        log.info("编辑外部联系人信息, EditCorpExternaluserHandler, param:{}", externalUserChageInfo);
        String corpId = externalUserChageInfo.getToUserName();
        String externalUserId = externalUserChageInfo.getExternalUserID();
        String userId = externalUserChageInfo.getUserID();


        PrivateSphere privateSphereRequest = new PrivateSphere();
        privateSphereRequest.setCorpId(corpId);
        privateSphereRequest.setProductId(aewcProductId);
        privateSphereRequest.setTemplateId(externalUserChageInfo.getTemplateId());
        SoaResponse<PrivateSphere, Void> sphereVoidSoaResponse = privateSphereService.fetch(privateSphereRequest);
        if (0L != Long.parseLong(sphereVoidSoaResponse.getReturnCode())) {
            log.warn("查询私域失败, request:{}, response:{}", privateSphereRequest, sphereVoidSoaResponse);
            String errorCode = BizErrorCodeGenerator.generate(MainBizDomainEnum.CUSTOMER_MANAGEMENT
                    , SubBizDomainEnum.CUSTOMER_LIST, CommonBizErrorEnum.ABNORMAL_DATA);
            return SoaUtil.error(errorCode, "查询私域失败,corpId:" + corpId, null);
        }

        PrivateSphere privateSphereResult = sphereVoidSoaResponse.getResponseVo();
        SelfExternalContactGetBO selfExternalContactGetBO = null;

        //2、判断员工是否存在 且在可见范围
        Employee employeeResult = employeeProxy.fetchEmployeeById(privateSphereResult, userId, null);
        if (Objects.isNull(employeeResult)) {
            log.warn("客户编辑事件-对应员工不存在，txUserId:{},corpId:{},externalUserId:{}", userId, corpId, externalUserId);
            String errorCode = BizErrorCodeGenerator.generate(MainBizDomainEnum.CUSTOMER_MANAGEMENT
                    , SubBizDomainEnum.CUSTOMER_LIST, CommonBizErrorEnum.ABNORMAL_DATA);
            return SoaUtil.error(errorCode, "编辑外部联系人消息，企微助手查询本地员工数据失败, request.userId:" + userId, null);
        }
        //员工未激活坐席，则不处理消息
        if (EmployeeActiveStatusEnum.INACTIVE.equals(employeeResult.getActiveStatus())) {
            log.warn("客户编辑事件-对应员工坐席未激活，txUserId:{},corpId:{},externalUserId:{}", employeeResult.getTxUserId(), corpId, externalUserId);
            String errorCode = BizErrorCodeGenerator.generate(MainBizDomainEnum.CUSTOMER_MANAGEMENT
                    , SubBizDomainEnum.CUSTOMER_LIST, CommonBizErrorEnum.ABNORMAL_DATA);
            return SoaUtil.error(errorCode, "客户编辑事件-对应员工坐席未激活，txUserId:" + userId, null);
        }

        try {
            // 2、获取本地企微用户信息（没有需要写入）
            List<Customer> customerList = new ArrayList<>();
            try {
                customerList = customerServiceProxy.fetchCustomerByIds(null, externalUserId, privateSphereResult);
            } catch (Exception e) {
                log.error("查询企微助手本地客户数据失败, externalUserId:{}, privateSphereId:{}", externalUserId, privateSphereResult.getPrivateSphereId());
            }

            if (CollectionUtils.isEmpty(customerList)) {
                //没查到客户，写入数据
                addCorpExternaluserHandler.handleCorpExternalUser(externalUserChageInfo);
            } else {
                //3. 调用腾讯，通过externalUserId查询企微客户详情
                RateLimit4CustomerDTO<ExternalUserChangeInfo> rateLimitDTO = new RateLimit4CustomerDTO<>();
                rateLimitDTO.setTaskId(externalUserChageInfo.getTaskId());
                rateLimitDTO.setBizLimitKey(BizLimitKeyEnum.EDIT_ADD_EXTERNAL_CONTACT_NOW.getKey());
                rateLimitDTO.setLimitKey(LimitKeyEnum.SLEF_EXTERNAL_CONTACT_GET.getKey());
                SoaResponse<SelfExternalContactGetBO, Void> selfExternalContactSoaResponse = channelAdapterServiceProxy.getSelfExternalContact(privateSphereResult, externalUserId, rateLimitDTO);
                String returnCode = selfExternalContactSoaResponse.getReturnCode();
                //3.1 接入限频
                if (CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode().equals(returnCode) || CommonBizErrorEnum.WECHAT_WORK_CONVERT_ID_LIMIT.getCode().equals(returnCode)) {
                    SelfExternalContactGetBO responseVo = selfExternalContactSoaResponse.getResponseVo();
                    if (Objects.nonNull(responseVo)) {
                        Long taskId = responseVo.getTaskId();
                        log.warn("编辑外部联系人调用腾讯接口被限频，taskId:{},msg：{}", taskId, selfExternalContactSoaResponse.getReturnMsg());
                        //创建一个限频的redis任务记录
                        RatelimiterInfo ratelimiterInfo = new RatelimiterInfo(rateLimitDTO.getLimitKey(), JSON.toJSONString(externalUserChageInfo), rateLimitDTO.getBizLimitKey());
                        redisTemplate.opsForValue().set(LimitKeyUtils.buildRedisKey(taskId), ratelimiterInfo, 1, TimeUnit.DAYS);

                        return SoaUtil.error(returnCode, "编辑外部联系人调用腾讯接口被限频，taskId:" + taskId, null);
                    }
                }

                if (0L != Long.parseLong(returnCode) || Objects.isNull(selfExternalContactSoaResponse.getResponseVo())) {
                    log.warn("编辑客户消息, 查询腾讯客户详情信息失败, response:{}", JSON.toJSONString(selfExternalContactSoaResponse));
                    String errorCode = BizErrorCodeGenerator.generate(MainBizDomainEnum.CUSTOMER_MANAGEMENT
                            , SubBizDomainEnum.CUSTOMER_LIST, CommonBizErrorEnum.ABNORMAL_DATA);
                    return SoaUtil.error(errorCode, "编辑客户消息, 查询腾讯客户详情信息失败", null);
                }

                selfExternalContactGetBO = selfExternalContactSoaResponse.getResponseVo();
                ExternalContactBO externalContactBO = selfExternalContactGetBO.getExternalContactBO();
                List<FollowUserBO> followUserList = selfExternalContactGetBO.getFollowUser();

                // 更新外部联系人基本信息
                String phone = customerCommonService.getCustomerPhone(followUserList);
                Customer customer = CustomerConvert.toCustomer(privateSphereResult, externalUserId, phone, externalContactBO);
                customer.setId(customerList.get(0).getId());

                SoaResponse<Customer, ?> customerSoaResponse = customerService.updateCustomer(customer);
                if (0L != Long.parseLong(customerSoaResponse.getReturnCode())) {
                    log.error("更新企微助手客户基本失败, request:{}, response:{}", JSON.toJSONString(customer), JSON.toJSONString(customerSoaResponse));
                }

                customer = customerSoaResponse.getResponseVo();
                if (StringUtils.isNotBlank(phone)) {
                    SoaResponse<Customer, ?> customerDetailSoaResponse = customerService.updateCustomerDeatil(customer);
                    if (0L != Long.parseLong(customerDetailSoaResponse.getReturnCode())) {
                        log.error("更新企微助手客户详情信息失败, request:{}, response:{}", JSON.toJSONString(customer), JSON.toJSONString(customerDetailSoaResponse));
                    }
                }

                for (FollowUserBO followUserBO : followUserList) {
                    if (followUserBO.getUserid().equals(userId)) {
                        CustomerEmployeeRelation customerEmpRelRequest = new CustomerEmployeeRelation();
                        customerEmpRelRequest.setCorpId(corpId);
                        customerEmpRelRequest.setEmployee(employeeResult);
                        customerEmpRelRequest.setCustomerId(customerList.get(0).getId());
                        customerEmpRelRequest.setRemark(followUserBO.getRemark());
                        customerEmpRelRequest.setRemarkCorpName(followUserBO.getRemarkCorpName());
                        customerEmpRelRequest.setDescription(followUserBO.getDescription());
                        customerService.updateCustomerEmployeeRelation(customerEmpRelRequest);

                        //5、cdp客户属性
                        try {

                            // 查询主客户wid
                            Long superWid = customerThird.getSuperWid(privateSphereResult.getBosId(), externalUserId, privateSphereResult.getCorpId());
                            if (Objects.isNull(superWid)) {
                                log.warn("编辑好友事件消息，未获取到wid,externalUserId:{}", externalUserId);
                                continue;
                            }

                            CDPUserMarkDTO cdpUserMarkDTO = new CDPUserMarkDTO();
                            cdpUserMarkDTO.setuKey(String.valueOf(superWid));
                            cdpUserMarkDTO.setuKeyType("wid");
                            cdpUserMarkDTO.setsChannelType(203);
                            cdpUserMarkDTO.setsChannelId(privateSphereResult.getProductInstanceId());
                            cdpUserMarkDTO.setBosId(privateSphereResult.getBosId());
                            cdpUserMarkDTO.setUpdateTime(String.valueOf(System.currentTimeMillis()));
                            CdpDataJsonInfo cdpDataJsonInfo = new CdpDataJsonInfo();
                            cdpDataJsonInfo.setProductInstanceId(privateSphereResult.getProductInstanceId());
                            cdpDataJsonInfo.setWid(superWid);
                            cdpDataJsonInfo.setCorpId(corpId);
                            cdpDataJsonInfo.setExternalUserId(externalUserId);
                            cdpDataJsonInfo.setWechatNickName(customer.getName());
                            cdpDataJsonInfo.setGender(customer.getGender().getCode());
                            cdpDataJsonInfo.setAddWay(followUserBO.getAddWay());
                            cdpDataJsonInfo.setAddWayDesc(ExternalUserAddWayEnum.getEnumBycode(followUserBO.getAddWay()).getDesc());
                            cdpDataJsonInfo.setCorpFullName(customer.getCorpFullName());
                            cdpDataJsonInfo.setAvatar(customer.getAvatar());
                            cdpDataJsonInfo.setRemark(followUserBO.getRemark());
                            cdpDataJsonInfo.setOrgUserId(employeeResult.getId());
                            cdpDataJsonInfo.setOrgUserName(employeeResult.getName());
                            cdpDataJsonInfo.setAddValue(externalUserChageInfo.getState());
                            cdpUserMarkDTO.setDataJson(JSONObject.parseObject(JSON.toJSONString(cdpDataJsonInfo)));
                            cdpUserMarkDTO.setCdpMarkTypeEnum(CDPMarkTypeEnum.CDP_USER_ATTRIBUTE);
                            cdpUserMarkDTO.setCdpMarkMessageEventEnum(CdpMarkMessageEventEnum.CUSTOMER_ATTRIBUTE);
                            log.info("新中台消费更新外部联系人消息cdp打点：request {}", JSON.toJSONString(cdpUserMarkDTO));
                            cdpUserAdapterService.markCDPUserMsg(cdpUserMarkDTO);

                        } catch (Exception e) {
                            log.info("外部联系人变更cdp打点失败, request:{}, error:{}", JSON.toJSONString(externalUserChageInfo), e);
                        }

                        break;
                    }
                }

                //调用新的客户标签同步方法
                try {
                    log.info("编辑外部联系人, 同步客户标签, bosId:{}, employeeId:{}, param:{}", privateSphereResult.getBosId(), employeeResult, JSON.toJSONString(selfExternalContactGetBO));
                    customerTagSyncService.syncCustomerTag(privateSphereResult, externalUserId, null, followUserList, employeeResult);
                } catch (Exception e) {
                    log.error("编辑外部联系人, 同步客户标签,error", e);
                }

            }
        } catch (Exception e) {
            log.error("外部联系人变更信息失败, externalUserChangeInfo:{}, e", JSON.toJSONString(externalUserChageInfo), e);
        }

        return SoaUtil.ok(null);
    }

}

